﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using TO3.Models;
using TO3.DAL;

namespace TO3.Controllers
{
    public class MatchController : Controller
    {
        private TournamentContext db = new TournamentContext();
        int activeRound;
        int tournamentId;

        // GET: /Match/
        public ActionResult Index()
        {
            //Get the active tournamentId (if any)
            if (Session["ActiveTournamentId"] == null)
            {
                this.tournamentId = 0;
            }
            else
            {
                this.tournamentId = (int)Session["ActiveTournamentId"];
                
                var tournament = db.Tournaments.Single(t => t.Id == this.tournamentId);

                //Get active round number            
                activeRound = tournament.ActiveRound;
                //Get the tournament name            
                ViewBag.TournamentName = db.Tournaments.Single(t => t.Id == tournamentId).Name;
            }

            //Check if the logged in user is an organiser or admin
            if (User.IsInRole("Organiser") || User.IsInRole("Admin"))
            {
                ViewBag.IsOrganiser = true;
            }
            else
            {
                ViewBag.IsOrganiser = false;
            }            

            //Only display the matches in the current tournament
            var matches = db.Matches.Where(m => m.TournamentId == this.tournamentId);

            return View(matches.ToList());
        }

        // GET: /Match/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Match match = db.Matches.Find(id);
            if (match == null)
            {
                return HttpNotFound();
            }
            return View(match);
        }

        // GET: /Match/Create
        [Authorize(Roles = "Organiser, Admin)")]
        public ActionResult Create()
        {
            ViewBag.Player1Id = new SelectList(db.Players, "Id", "Name");
            ViewBag.Player2Id = new SelectList(db.Players, "Id", "Name");
            ViewBag.TournamentId = new SelectList(db.Tournaments, "Id", "Name");
            ViewBag.WinnerId = new SelectList(db.Players, "Id", "Name");
            return View();
        }

        // POST: /Match/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        [Authorize(Roles = "Organiser, Admin)")]
        public ActionResult Create([Bind(Include="Id,TournamentId,Player1Id,Player2Id,TableId,Round,Player1CP,Player2CP,WinnerId")] Match match)
        {
            if (ModelState.IsValid)
            {
                db.Matches.Add(match);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            ViewBag.Player1Id = new SelectList(db.Players, "Id", "Name", match.Player1Id);
            ViewBag.Player2Id = new SelectList(db.Players, "Id", "Name", match.Player2Id);
            ViewBag.TournamentId = new SelectList(db.Tournaments, "Id", "Name", match.TournamentId);
            ViewBag.WinnerId = new SelectList(db.Players, "Id", "Name", match.WinnerId);
            return View(match);
        }

        // GET: /Match/MatchAll
        [Authorize(Roles = "Organiser, Admin)")]
        public ActionResult MatchAll()
        {
            if (Session["ActiveTournamentId"] == null)
            {
                this.tournamentId = 0;
            }
            else
            {
                this.tournamentId = (int)Session["ActiveTournamentId"];
            }
            var tournament = db.Tournaments.Single(t => t.Id == this.tournamentId);

            //Get active round number            
            this.activeRound = tournament.ActiveRound;

            try
            {
                MatchMaker.CreateMatches(this.tournamentId, this.activeRound);
            }
            catch (System.InvalidOperationException)
            {
                //Do nothing for now, we will have to display below information in the page later.
                string errorMessage = "Could not create any more matches, the leading player has played every other player";
                Session.Add("ErrorMessage", errorMessage);
            }            

            return RedirectToAction("Index");
        }


        // GET: /Match/Edit/5
        [Authorize(Roles = "Organiser, Admin)")]
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Match match = db.Matches.Find(id);
            if (match == null)
            {
                return HttpNotFound();
            }                       

            ViewBag.Player1Id = new SelectList(db.Players, "Id", "Name", match.Player1Id);
            ViewBag.Player2Id = new SelectList(db.Players, "Id", "Name", match.Player2Id);
            ViewBag.TournamentId = new SelectList(db.Tournaments, "Id", "Name", match.TournamentId);

            var matchPlayers = from p in db.Players
                               where p.Id == match.Player1Id || p.Id == match.Player2Id
                               select p;

            ViewBag.WinnerId = new SelectList(matchPlayers, "Id", "Name", match.WinnerId);
            return View(match);
        }

        // POST: /Match/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        [Authorize(Roles = "Organiser, Admin)")]
        public ActionResult Edit([Bind(Include="Id,TournamentId,Player1Id,Player2Id,TableId,Round,Player1CP,Player2CP,WinnerId")] Match match)
        {
            if (ModelState.IsValid)
            {
                db.Entry(match).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            ViewBag.Player1Id = new SelectList(db.Players, "Id", "Name", match.Player1Id);
            ViewBag.Player2Id = new SelectList(db.Players, "Id", "Name", match.Player2Id);
            ViewBag.TournamentId = new SelectList(db.Tournaments, "Id", "Name", match.TournamentId);
            
            var matchPlayers = from p in db.Players
                               where p.Id == match.Player1Id || p.Id == match.Player2Id
                               select p;

            ViewBag.WinnerId = new SelectList(matchPlayers, "Id", "Name", match.WinnerId);
            return View(match);
        }

        // GET: /Match/Delete/5
        [Authorize(Roles = "Organiser, Admin)")]
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Match match = db.Matches.Find(id);
            if (match == null)
            {
                return HttpNotFound();
            }
            return View(match);
        }

        // POST: /Match/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        [Authorize(Roles = "Organiser, Admin)")]
        public ActionResult DeleteConfirmed(int id)
        {
            Match match = db.Matches.Find(id);
            db.Matches.Remove(match);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}
